home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / gpt32src.zip / LATEX.TRM < prev    next >
Text File  |  1992-03-25  |  19KB  |  665 lines

  1. /*
  2.  * $Id: latex.trm,v 3.26 92/03/24 22:35:37 woo Exp Locker: woo $
  3.  */
  4.  
  5. /* GNUPLOT - latex.trm */
  6. /*
  7.  * Copyright (C) 1990, 1991, 1992   
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted, 
  11.  * provided that the above copyright notice appear in all copies and 
  12.  * that both that copyright notice and this permission notice appear 
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the modified code.  Modifications are to be distributed 
  17.  * as patches to released version.
  18.  *  
  19.  * This software  is provided "as is" without express or implied warranty.
  20.  * 
  21.  * This file is included by ../term.c.
  22.  *
  23.  * This terminal driver supports:
  24.  *   LaTeX pictures (latex).
  25.  *   LaTeX pictures with emTeX specials (emtex). 
  26.  *
  27.  * AUTHORS
  28.  *   David Kotz, Russell Lang
  29.  *
  30.  * send your comments or suggestions to (info-gnuplot@ames.arc.nasa.gov).
  31.  * 
  32.  */
  33.  
  34. /* modified to optimize use of \rule for long lines */
  35.  
  36. /* the following LATEX driver has been modified by 
  37.    Russell Lang, eln272v@monu1.cc.monash.oz from the
  38.    GnuTeX 1.3 driver by David Kotz, David.Kotz@Dartmouth.edu.
  39.    Since then it has been further extended by David Kotz.
  40.    EmTeX driver by Russell Lang. */
  41.  
  42.  
  43. #define LATEX_PTS_PER_INCH (72.27)
  44. #define DOTS_PER_INCH (300)    /* resolution of printer we expect to use */
  45. #define LATEX_UNIT (LATEX_PTS_PER_INCH/DOTS_PER_INCH) /* dot size in pt */
  46.  
  47. /* 5 inches wide by 3 inches high (default) */
  48. #define LATEX_XMAX (5*DOTS_PER_INCH)  /* (LATEX_PTS_PER_INCH/LATEX_UNIT*5.0) */
  49. #define LATEX_YMAX (3*DOTS_PER_INCH)  /* (LATEX_PTS_PER_INCH/LATEX_UNIT*3.0) */
  50.  
  51. #define LATEX_HTIC (5*DOTS_PER_INCH/72)        /* (5./LATEX_UNIT) */
  52. #define LATEX_VTIC (5*DOTS_PER_INCH/72)        /* (5./LATEX_UNIT) */
  53. #define LATEX_HCHAR (DOTS_PER_INCH*53/10/72)    /* (5.3/LATEX_UNIT) */
  54. #define LATEX_VCHAR (DOTS_PER_INCH*11/72)    /* (11./LATEX_UNIT) */
  55.  
  56. static int LATEX_posx;
  57. static int LATEX_posy;
  58. static enum JUSTIFY latex_justify=LEFT;
  59. static int latex_angle=0;
  60.  
  61. /* Default line-drawing character */
  62. /* the definition of plotpoint varies with linetype */
  63. #define LATEX_DOT "\\usebox{\\plotpoint}"
  64. #define LATEX_TINY_DOT "\\rule{.1pt}{.1pt}" /* for dots plot style */
  65.  
  66. /* POINTS */
  67. #define LATEX_POINT_TYPES 12    /* we supply more point types */
  68. static char *LATEX_points[] = {
  69.     "\\raisebox{-1.2pt}{\\makebox(0,0){$\\Diamond$}}",
  70.     "\\makebox(0,0){$+$}",
  71.     "\\raisebox{-1.2pt}{\\makebox(0,0){$\\Box$}}",
  72.     "\\makebox(0,0){$\\times$}",
  73.     "\\makebox(0,0){$\\triangle$}",
  74.     "\\makebox(0,0){$\\star$}",
  75.     "\\circle{12}", "\\circle{18}", "\\circle{24}",
  76.     "\\circle*{12}", "\\circle*{18}", "\\circle*{24}"
  77. };
  78.  
  79. /* LINES */
  80. static float LATEX_size = 0;    /* current thick of line in points */
  81. static float LATEX_dotspace = 0; /* current dotspace of line in points */
  82. #define LATEX_LINE_TYPES 6    /* number of line types below */
  83. #define LATEX_THIN_LINE 0    /* the thinnest solid line type */
  84. static struct {
  85.     float size;            /* size of dot, or thick of line in points */
  86.     float dotspace;            /* inter-dot space in points; 0 for lines */
  87. } LATEX_lines[] = {
  88.     {.35, 0.0},                /* thin solid line */
  89.     {.7, 0.0},                /* thick solid line */
  90.     {1.0, 0.0},                /* Thick solid line */
  91.     {.5, 5.0},                /* dotted line */
  92.     {.5, 9.0},                /* widely dotted line */
  93.     {.5, 13.0}                /* really widely dotted line */
  94. };
  95. /* for drawing dotted and solid lines */
  96. static void LATEX_dot_line();
  97. static void LATEX_solid_line();
  98. static void LATEX_rule();
  99. static void LATEX_flushdot();
  100. #define LATEX_flushrule() LATEX_rule(2, 0.,0.,0.,0.) /* flush old rule */
  101. static BOOLEAN LATEX_moved = TRUE;    /* pen is up after move */
  102. static float LATEX_dotsize;    /* size of LATEX_DOT in units */
  103. static BOOLEAN LATEX_needsdot = FALSE;/* does dotted line need termination? */
  104.  
  105. #ifdef EMTEX
  106. BOOLEAN emtex=FALSE; /* not currently using emtex */
  107. static void EMTEX_solid_line();
  108. #endif
  109.  
  110. /* ARROWS */
  111. /* the set of non-vertical/non-horizontal LaTeX vector slopes */
  112. /* except negatives - they are handled specially */
  113. static struct vslope {
  114.     int dx, dy;
  115. } LATEX_slopes[] = {
  116.     {1,1}, {1,2}, {1,3}, {1,4},
  117.     {2,1}, {2,3},
  118.     {3,1}, {3,2}, {3,4},
  119.     {4,1}, {4,3},
  120.     {0,0}                    /* terminator */
  121. };
  122. static void best_latex_arrow(); /* figure out the best arrow */
  123.  
  124. LATEX_init()
  125. {
  126. #ifdef EMTEX
  127.     emtex = FALSE;
  128. #endif
  129.     LATEX_posx = LATEX_posy = 0;
  130.     fprintf(outfile, "%% GNUPLOT: LaTeX picture\n");
  131.     fprintf(outfile, "\\setlength{\\unitlength}{%fpt}\n", LATEX_UNIT);
  132.     fprintf(outfile, 
  133.           "\\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n");
  134.     LATEX_linetype(-1);
  135.     LATEX_size =0;
  136. }
  137.  
  138.  
  139. LATEX_scale(xs, ys)
  140.     double xs, ys;            /* scaling factors */
  141. {
  142.     register struct termentry *t = &term_tbl[term];
  143.  
  144.     /* we change the table for use in graphics.c and LATEX_graphics */
  145.     t->xmax = (unsigned int)(LATEX_XMAX * xs);
  146.     t->ymax = (unsigned int)(LATEX_YMAX * ys);
  147.  
  148.     return(TRUE);
  149. }
  150.  
  151. LATEX_graphics()
  152. {
  153.     register struct termentry *t = &term_tbl[term];
  154.  
  155.     fprintf(outfile, "\\begin{picture}(%d,%d)(0,0)\n", t->xmax, t->ymax);
  156.     fprintf(outfile, "\\tenrm\n");
  157. }
  158.  
  159.  
  160. LATEX_text()
  161. {
  162.     LATEX_flushrule();
  163.     LATEX_flushdot();
  164.     fprintf(outfile, "\\end{picture}\n");
  165.     LATEX_posx = LATEX_posy = 0; /* current position */
  166.     LATEX_moved = TRUE;    /* pen is up after move */
  167. }
  168.  
  169. LATEX_linetype(linetype)
  170.     int linetype;
  171. {
  172.     float size;
  173.  
  174.     if (linetype >= LATEX_LINE_TYPES)
  175.      linetype %= LATEX_LINE_TYPES;
  176.  
  177. #ifdef EMTEX
  178.     if (!emtex)
  179. #endif
  180.     LATEX_flushrule();
  181.     LATEX_flushdot();
  182.  
  183.     /* Find the new desired line thickness. */
  184.     /* negative linetypes (for axes) use a thin line */
  185.     /* only relevant for drawing axes/border in 3d */
  186.     size = (linetype >= 0 ? LATEX_lines[linetype].size 
  187.           : LATEX_lines[LATEX_THIN_LINE].size);
  188.  
  189.     /* If different from current size, redefine \plotpoint */
  190.     if (size != LATEX_size) {
  191.        fprintf(outfile, 
  192.              "\\sbox{\\plotpoint}{\\rule[%.3fpt]{%.3fpt}{%.3fpt}}%%\n",
  193.              -size/2, size, size);
  194. #ifdef EMTEX
  195.         if (emtex)         /* change line width */
  196.         fprintf(outfile, "\\special{em:linewidth %.1fpt}%%\n", size);
  197. #endif
  198.     }
  199.     
  200.     LATEX_size = size;
  201.     LATEX_dotsize = size / LATEX_UNIT;
  202.     LATEX_dotspace = (linetype >= 0) ? LATEX_lines[linetype].dotspace : 0;
  203.     LATEX_moved = TRUE;            /* reset */
  204. }
  205.  
  206. LATEX_move(x,y)
  207.     unsigned int x,y;
  208. {
  209.     LATEX_flushdot();
  210.  
  211.     LATEX_posx = x;
  212.     LATEX_posy = y;
  213.     LATEX_moved = TRUE;            /* reset */
  214. }
  215.  
  216.  
  217. LATEX_point(x,y, number)        /* version of line_and_point */
  218.     unsigned int x,y;
  219.     int number;                /* type of point */
  220. {
  221.     LATEX_move(x,y);
  222.     
  223.     /* Print the character defined by 'number'; number < 0 means 
  224.       to use a dot, otherwise one of the defined points. */
  225.     fprintf(outfile, "\\put(%d,%d){%s}\n", x, y, 
  226.           (number < 0 ? LATEX_TINY_DOT
  227.            : LATEX_points[number % LATEX_POINT_TYPES]));
  228. }
  229.  
  230.  
  231. LATEX_vector(ux,uy)
  232.     unsigned int ux,uy;
  233. {
  234.     if (LATEX_dotspace == 0.0) {
  235.        /* solid line */
  236. #ifdef EMTEX
  237.        if (emtex)
  238.         EMTEX_solid_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  239.        else
  240. #endif
  241.         LATEX_solid_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  242.     } else
  243.      /* dotted line */
  244.      LATEX_dot_line(LATEX_posx, (int)ux, LATEX_posy, (int)uy);
  245.  
  246.     LATEX_posx = ux;
  247.     LATEX_posy = uy;
  248. }
  249.  
  250. static void
  251. LATEX_solid_line(x1,x2, y1,y2)
  252.     int x1,x2, y1,y2;
  253. {
  254.     float slope;
  255.     int inc;
  256.     float next;
  257.     float x,y;
  258.     int code;                /* possibly combine with previous rule */
  259.  
  260.     /* we draw a solid line using the current line thickness (size) */
  261.     /* we do it with lots of \\rules */
  262.  
  263.     if (x1 == x2 && y1 == y2) { /* zero-length line - just a dot */
  264.        if (LATEX_moved) {
  265.           LATEX_flushrule();
  266.           /* plot a dot */
  267.           fprintf(outfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  268.        }
  269.     } else {
  270.        code = (LATEX_moved ? 0 : 1); /* no combine after move */
  271.        if (x1 == x2)        /* vertical line - special case */
  272.         LATEX_rule(code, (double)x1, (double)y1,
  273.                LATEX_dotsize, (double)y2-y1);
  274.        else if (y1 == y2)    /* horizontal line - special case */
  275.         LATEX_rule(code, (double)x1, (double)y1, (double)x2-x1,
  276.                LATEX_dotsize);
  277.        else {
  278.           slope = ((float)y2-y1)/((float)x2-x1);
  279.           if (abs(slope) <= 1.0) {
  280.              /* longer than high */
  281.              inc = sign(y2-y1);
  282.              for (x = x1, y = y1; (y2-y)*inc >= 0; y += inc) {
  283.                 next = inc/slope + x;
  284.                 if ((x2>x1 && next > x2) || (x2<x1 && next < x2)) {
  285.                     LATEX_rule(code, x,y, x2-x, LATEX_dotsize);
  286.                     break;
  287.                 } else {
  288.                     LATEX_rule(code, x,y, next-x, LATEX_dotsize);
  289.                     x = next;
  290.                 }
  291.                 code = 0;
  292.              }
  293.           } else {
  294.              /* higher than long */
  295.              inc = sign(x2-x1);
  296.              for (x = x1, y = y1; (x2-x)*inc >= 0; x += inc) {
  297.                 next = inc*slope + y;
  298.                 if ((y2>y1 && next > y2) || (y2<y1 && next < y2)) {
  299.                     LATEX_rule(code, x,y, LATEX_dotsize, y2-y);
  300.                     break;
  301.                 } else {
  302.                     LATEX_rule(code, x,y, LATEX_dotsize, next-y);
  303.                     y = next;
  304.                 }
  305.                 code = 0;
  306.              }
  307.           }
  308.        }
  309.     }
  310.     LATEX_moved = FALSE;
  311. }
  312.  
  313. /* Draw a \rule. Width or height may be negative; we can correct.
  314.  * The rule is never output immediately. The previous rule is output
  315.  * as-is if code is 0, and the previous rule is
  316.  * combined with the current rule (if possible) if code is 1.
  317.  * The previous rule is output, and the new one ignored, if code is 2.
  318.  */
  319. static void
  320. LATEX_rule(code, x,y, width, height)
  321.     int code;                /* how do we treat this rule? */
  322.     double x, y;
  323.     double width;
  324.     double height;
  325. {  
  326.     static float lastx, lasty;
  327.     static float lastw, lasth;
  328.     static BOOLEAN valid = FALSE; /* is 'last' data valid? */
  329.     BOOLEAN combine = (code == 1);
  330.     BOOLEAN flush = (code == 2);
  331.  
  332.     if (!flush)
  333.      if (width == 0 || height == 0)
  334.        return;            /* ignore this rule */
  335.  
  336.     if (valid && combine) {
  337.        /* try to combine new rule with old rule */
  338.        if ((int)lastx == (int)x && lastw == width) { /* vertical rule */
  339.           if (lasth * height >= 0) { /* same sign */
  340.              lasth += height;
  341.              return;
  342.           }
  343.        } else if ((int)lasty == (int)y && lasth == height){ /* horiz rule */
  344.           if (lastw * width >= 0) { /* same sign */
  345.              lastw += width;
  346.              return;
  347.           }
  348.        }
  349.        /* oh well, output last and remember the new one */
  350.     }
  351.  
  352.     if (valid) {
  353.        /* output the rule */
  354.        if (lastw < 0) {
  355.           lastx += lastw;
  356.           lastw = -lastw;
  357.        }
  358.        if (lasth < 0) {
  359.           lasty += lasth;
  360.           lasth = -lasth;
  361.        }
  362.  
  363.        /* if very small use canned dot */
  364.        if (lastw < LATEX_dotsize || lasth < LATEX_dotsize)
  365.         fprintf(outfile, "\\put(%d,%d){%s}\n",       
  366.                (int)lastx, (int)lasty, LATEX_DOT);
  367.        else
  368.         fprintf(outfile, "\\put(%d,%d){\\rule[%.3fpt]{%.3fpt}{%.3fpt}}\n",
  369.                (int)lastx, (int)lasty, -LATEX_dotsize*LATEX_UNIT/2,
  370.                lastw*LATEX_UNIT, lasth*LATEX_UNIT);
  371.     }
  372.     
  373.     if (flush) {
  374.        valid = FALSE;
  375.     } else {
  376.        lastx = x; lasty = y;
  377.        lastw = width; lasth = height;
  378.        valid = TRUE;
  379.     }
  380. }
  381.  
  382. static void
  383. LATEX_dot_line(x1,x2, y1,y2)
  384.     int x1,x2, y1,y2;
  385. {
  386.     static float LATEX_left;    /* fraction of space left after last dot */
  387. #ifndef AMIGA_AC_5
  388.     extern double sqrt();
  389. #endif
  390.     /* we draw a dotted line using the current dot spacing */
  391.  
  392.     if (LATEX_moved)
  393.      LATEX_left = 1.0;        /* reset after a move */
  394.  
  395.     /* zero-length line? */
  396.     if (x1 == x2 && y1 == y2) {
  397.        if (LATEX_moved)
  398.         /* plot a dot */
  399.         fprintf(outfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  400.     } else {
  401.        float dotspace = LATEX_dotspace / LATEX_UNIT;
  402.        float x,y;            /* current position */
  403.        float xinc, yinc;    /* increments */
  404.        float slope;        /* slope of line */
  405.        float lastx = -1;    /* last x point plotted */
  406.        float lasty = -1;    /* last y point plotted */
  407.  
  408.        /* first, figure out increments for x and y */
  409.        if (x2 == x1) {
  410.           xinc = 0.0;
  411.           yinc = (y2-y1>0)?dotspace:-dotspace;
  412.        } else {
  413.           slope = ((float)y2-y1)/((float)x2-x1);
  414.           xinc = dotspace / sqrt(1 + slope*slope) * sign(x2-x1);
  415.           yinc = slope * xinc;
  416.        }
  417.        
  418.        /* now draw the dotted line */
  419.        /* we take into account where we last placed a dot */
  420.        for (x=x1 + xinc*(1-LATEX_left), y=y1 + yinc*(1-LATEX_left);
  421.            (x2-x)*xinc >= 0 && (y2-y)*yinc >= 0; /* same sign or zero */
  422.            lastx = x, x += xinc, 
  423.            lasty = y, y += yinc)
  424.         fprintf(outfile, "\\put(%d,%d){%s}\n", (int)x, (int)y, LATEX_DOT);
  425.  
  426.        /* how much is left over, as a fraction of dotspace? */
  427.        if (xinc != 0.0)            /* xinc must be nonzero */
  428.         if (lastx >= 0)
  429.           LATEX_left = abs(x2 - lastx) / abs(xinc);
  430.         else
  431.           LATEX_left += abs(x2-x1) / abs(xinc);
  432.        else
  433.         if (lasty >= 0)
  434.           LATEX_left = abs(y2 - lasty) / abs(yinc);
  435.         else
  436.           LATEX_left += abs(y2-y1) / abs(yinc);
  437.     }
  438.  
  439.     LATEX_needsdot = (LATEX_left > 0);
  440.  
  441.     LATEX_moved = FALSE;
  442. }
  443.  
  444. static void
  445. LATEX_flushdot()
  446. {
  447.     if (LATEX_needsdot) 
  448.      fprintf(outfile, "\\put(%d,%d){%s}\n", 
  449.             LATEX_posx, LATEX_posy, LATEX_DOT);
  450.     LATEX_needsdot = FALSE;
  451. }
  452.  
  453. LATEX_arrow(sx,sy, ex,ey, head)
  454.     int sx,sy, ex,ey;
  455.     BOOLEAN head;
  456. {
  457.     best_latex_arrow(sx,sy, ex,ey, 1, head);
  458.  
  459.     LATEX_posx = ex;
  460.     LATEX_posy = ey;
  461. }
  462.  
  463. static void best_latex_arrow(sx,sy, ex,ey, who, head)
  464.     int sx,sy, ex,ey;        /* start and end points */
  465.     int who;                /* 1=LATEX, 2=EEPIC */
  466.     BOOLEAN head;
  467. {
  468.     int dx = ex - sx;
  469.     int dy = ey - sy;
  470.     int x, y;                /* points near sx,sy */
  471.     float m;                /* slope of line */
  472.     float arrowslope;        /* slope of arrow */
  473.     float minerror = 0;        /* best-case error */
  474.     struct vslope *slope;    /* one of the slopes */
  475.     struct vslope *bestslope;    /* the slope with min error */
  476.     BOOLEAN horiz;            /* was it the horiz line that was best? */
  477.  
  478.     /* We try to draw a real arrow (ie, \vector). If we can't get
  479.     * a slope that is close, we draw a bent arrow.
  480.     */
  481.  
  482.     if (dx == 0) {
  483.        /* vertical arrow */
  484.        fprintf(outfile, "\\put(%d,%d){\\%s(0,%d){%d}}\n",
  485.              sx, sy, head ? "vector":"line", 
  486.              sign(ey-sy), abs(ey-sy));
  487.     } else if (dy == 0) {
  488.        /* horizontal arrow */
  489.        fprintf(outfile, "\\put(%d,%d){\\%s(%d,0){%d}}\n",
  490.              sx, sy, head ? "vector":"line",
  491.              sign(ex-sx), abs(ex-sx));
  492.     } else {
  493.        /* Slanted arrow. We'll give it a try.
  494.         * we try to find the closest-slope arrowhead.
  495.         */
  496.        bestslope = NULL;
  497.        minerror = 0; /* to shut up turbo C */
  498.        m = abs((float)dy/dx); /* the slope we want */
  499.        for (slope = LATEX_slopes; slope->dx != 0.0; slope++) {
  500.           /* find the slope of the arrow */
  501.           arrowslope = (float) slope->dy / slope->dx;
  502.           if (bestslope == NULL || abs(m-arrowslope) < minerror) {
  503.              minerror = abs(m-arrowslope);
  504.              bestslope = slope;
  505.           }
  506.        }
  507.  
  508.        /* now we have the best slope arrow */
  509.        /* maybe it's exactly the right slope! */
  510.        if (minerror == 0.0)    /* unlikely but possible */
  511.         fprintf(outfile, "\\put(%d,%d){\\%s(%d,%d){%d}}\n",
  512.                sx, sy, head ? "vector" : "line",
  513.                bestslope->dx*sign(ex-sx), bestslope->dy*sign(ey-sy),
  514.                abs(ex-sx));
  515.        else {
  516.           /* we draw the line the usual way, with thin lines */
  517. #ifdef EMTEX
  518.           if (emtex) {
  519.              LATEX_linetype(LATEX_THIN_LINE);
  520.              EMTEX_solid_line(sx,ex,sy,ey);
  521.           } else 
  522. #endif
  523.             if (who == 1) {
  524.                LATEX_linetype(LATEX_THIN_LINE);
  525.                LATEX_solid_line(sx,ex,sy,ey);
  526.             }
  527. #ifdef EEPIC
  528.             else {
  529.                EEPIC_move(sx,sy);
  530.                EEPIC_vector(ex,ey);
  531.             }
  532. #endif /* EEPIC */
  533.           /* and then draw an arrowhead (a short vector) there */
  534.             if (head)
  535.                   fprintf(outfile, "\\put(%d,%d){\\vector(%d,%d){0}}\n",
  536.                 ex, ey, 
  537.                 bestslope->dx*sign(ex-sx), bestslope->dy*sign(ey-sy));
  538.        }
  539.     }
  540. }
  541.  
  542.  
  543. LATEX_put_text(x, y, str)
  544.     int x,y;                /* reference point of string */
  545.     char str[];            /* the text */
  546. {
  547.     /* ignore empty strings */
  548.     if (str[0] == '\0')
  549.      return;
  550.  
  551.     fprintf(outfile, "\\put(%d,%d)",x,y);
  552.     switch(latex_angle) {  
  553.         case 0: {
  554.           switch(latex_justify) {
  555.              case LEFT: {
  556.                 fprintf(outfile,
  557.                        "{\\makebox(0,0)[l]{%s}}\n", str);
  558.                 break;
  559.              }
  560.              case CENTRE: {
  561.                 fprintf(outfile,
  562.                        "{\\makebox(0,0){%s}}\n", str);
  563.                 break;
  564.              }
  565.              case RIGHT: {
  566.                 fprintf(outfile,
  567.                        "{\\makebox(0,0)[r]{%s}}\n", str);
  568.                 break;
  569.              }
  570.           }
  571.           break;
  572.        }
  573.        case 1: {            /* put text in a short stack */
  574.           switch(latex_justify) {
  575.              case LEFT: {
  576.                 fprintf(outfile,
  577.                        "{\\makebox(0,0)[lb]{\\shortstack{%s}}}\n", str);
  578.                 break;
  579.              }
  580.              case CENTRE: {
  581.                 fprintf(outfile,
  582.                        "{\\makebox(0,0)[l]{\\shortstack{%s}}}\n", str);
  583.                 break;
  584.              }
  585.              case RIGHT: {
  586.                 fprintf(outfile,
  587.                        "{\\makebox(0,0)[lt]{\\shortstack{%s}}}\n", str);
  588.                 break;
  589.              }
  590.           }
  591.           break;
  592.        }    
  593.     }
  594. }
  595.  
  596.  
  597.  
  598. int LATEX_justify_text(mode)
  599.     enum JUSTIFY mode;
  600. {
  601.     latex_justify = mode;
  602.     return (TRUE);
  603. }
  604.  
  605. int LATEX_text_angle(angle)
  606.     int angle;
  607. {
  608.     /* we can't really write text vertically, but this will 
  609.       put the ylabel centred at the left of the plot, and
  610.       then we'll make a \shortstack */
  611.     latex_angle = angle;
  612.     return (TRUE);
  613. }
  614.  
  615. LATEX_reset()
  616. {
  617.     LATEX_posx = LATEX_posy = 0; /* current position */
  618.     LATEX_moved = TRUE;    /* pen is up after move */
  619. }
  620.  
  621.  
  622. #ifdef EMTEX
  623.  
  624. EMTEX_init()
  625. {
  626.     emtex=TRUE;
  627.     LATEX_posx = LATEX_posy = 0;
  628.     fprintf(outfile, "%% GNUPLOT: LaTeX picture with emtex specials\n");
  629.     fprintf(outfile, "\\setlength{\\unitlength}{%fpt}\n", LATEX_UNIT);
  630.     fprintf(outfile, 
  631.           "\\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n");
  632.     LATEX_linetype(-1);
  633. }
  634.  
  635.  
  636. EMTEX_reset()
  637. {
  638.     emtex=FALSE;
  639.     LATEX_posx = LATEX_posy = 0;
  640. }
  641.  
  642.  
  643. EMTEX_text()
  644. {
  645.     fprintf(outfile, "\\end{picture}\n");
  646. }
  647.  
  648.  
  649. static void
  650. EMTEX_solid_line(x1,x2, y1,y2)
  651.     int x1,x2, y1,y2;
  652. {
  653.     /* emtex special solid line */
  654.     if (LATEX_moved)
  655.         fprintf(outfile, "\\put(%d,%d){\\special{em:moveto}}\n", x1, y1);
  656.     if ( (x1!=x2) || (y1!=y2) )
  657.         fprintf(outfile, "\\put(%d,%d){\\special{em:lineto}}\n", x2, y2);
  658.     LATEX_posx = x2;
  659.     LATEX_posy = y2;
  660.     LATEX_moved = FALSE;
  661. }
  662.  
  663.  
  664. #endif /* EMTEX */
  665.